package cn.wolfcode.wolf2w.service.impl;

import cn.wolfcode.wolf2w.domain.Destination;
import cn.wolfcode.wolf2w.domain.Region;
import cn.wolfcode.wolf2w.query.DestinationQuery;
import cn.wolfcode.wolf2w.repository.DestinationRepository;
import cn.wolfcode.wolf2w.service.IDestinationService;
import cn.wolfcode.wolf2w.service.IRegionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
public class DestinationServiceImpl implements IDestinationService {
    @Autowired
    private DestinationRepository destinationRepository;
    @Autowired
    private IRegionService regionService;
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void save(Destination destination) {
        destination.setId(null);
        destinationRepository.save(destination);
    }

    //查询单个目的地对象
    @Override
    public Destination get(String id) {
        Destination byId = destinationRepository.findById(id).orElse(null);
//强转
        return byId;//如果是空是就返回空值,否则返回对象
    }

    @Override
    public List<Destination> listAll() {
        List<Destination> destinations = destinationRepository.findAll();
        return destinations;
    }

    @Override
    public void delete(String id) {
        destinationRepository.deleteById(id);
    }

    //修改操作
    @Override
    public void update(Destination destination) {
        destinationRepository.save(destination);
//如果对象有id就是新增操作,没有就是修改操作
//        比如:下面where 子句 id=xx ,就是新增操作
//      db.users  insertOne({

////                {
////                    "age":20;
////                }
////        })

    }


    /**
     * 根据区域对象的id获取目的地对象集合
     *
     * @param rid
     * @return 目的地对象集合
     */
    @Override
    public List<Destination> getDestByRegionId(String rid) {
        Region region = (Region) regionService.get(rid);
        //获取区域对象的refIds,它是一个数组,里面装的是目的地的id
        List<String> ids = region.getRefIds();
        //根据目的地id获取目的地对象集合
        return destinationRepository.findByIdIn(ids);
    }

    @Override
    public List<Destination> getDestByDeep(int deep) {

        return destinationRepository.findByDeep(deep);
    }

    /**
     * 修改操作
     *
     * @param destination
     */
    @Override
    public void updateInfo(Destination destination) {
        //查询

        Destination destination1 = this.get(destination.getId());
        //替换
        //destination.getInfo()用用户
        destination1.setInfo(destination.getInfo());
        //更新
        this.update(destination1);

    }

    @Override
    public Page<Destination> query(DestinationQuery qo) {
        Query query = new Query();
        long rows = mongoTemplate.count(query, Destination.class);
        if (rows == 0) {
            return Page.empty();
        }

        //属于吐司(位置导航)操作的一部分
        //拼接sql  用来查询  比如:用户点击中国目的地对象,就把它的id传到后台,就根据中国的id去查询所有的省份对象出来,
        // qo对象定义了一个属性parentId用来装中国目的地对象的id的值

        if (qo.getParentId() != null) {
            //条件对象
            Criteria criteria = Criteria.where("parentId").is(qo.getParentId());
            //添加条件对象到查询对象,等添加分页对象到查询对象后,再一起拼接成sql:根据查询结果集合,同时分页排序
            query.addCriteria(criteria);
        }
        //高级查询
        if (qo.getKeyword() != null) {
            //条件对象
            Criteria criteria = Criteria.where("name").regex(qo.getKeyword());
            //添加条件对象到查询对象,等添加分页对象到查询对象后,再一起拼接成sql:根据查询结果集合,同时分页排序
            query.addCriteria(criteria);
        }

        //分页对象  用来做分页排序   默认是根据id来排序
        Pageable pageable = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.ASC, "_id");
//        添加分页对象到查询对象
        query.with(pageable);
        //拼接成sql:根据查询结果集合,同时分页排序
        List<Destination> list = mongoTemplate.find(query, Destination.class);
        //结果集合,分页对象,总数据条数
        return new PageImpl<>(list, pageable, rows);
    }

    //吐司(导航地址)
    @Override
    public List<Destination> queryByParentId(String parentId) {
//        假设用户点击广东,传来了parentId变量: 广东目的地对象的id字段值
        //如果没有值,就返回空集合
        if (!StringUtils.hasLength(parentId)) {
            return Collections.emptyList();
        }
        List<Destination> list = new ArrayList<>();
        //获取optional对象,再获取目的地对象
        //根据广东目的地对象的id字段值获取出广东目的地对象
        Optional<Destination> optional = destinationRepository.findById(parentId);
//        不是null就输出目的地对象.比如:广东目的地对象
        Destination destination = optional.orElse(null);
        list.add(destination);
        while (true) {
            if (destination.getParentId() == null) {
                //如果某个目的地对象如:广东目的地对象的parentId等于空值,就终止循环,执行循环外面的逻辑了
                break;

            } else {
                //如果某个目的地对象如:对象广东目的地对象的parentId不等于空值,
                // 就根据广东目的地对象的parentId字段获取出中国目的地对象(广东目的地对象的parentId等于中国目的地对象的id)
//                然后继续循环判断parentId等不等于空值,
                destination = destinationRepository.findById(destination.getParentId()).get();
//                Destination destination1 = optional.orElse(null);
                list.add(destination);

            }
        }
        Collections.reverse(list);//list集合顺序{1,2,3}反转成{3,2,1}
        return list;//返回给前端显示
    }

    //目的地列表控制显示:
    @Override
    public List<Destination> getDestByRegionIdForApi(String regionId) {
        List<Destination> destinations = null;
        //第一层:关联的目的地
        //如果是中国,查询所有省份
        if ("-1".equals(regionId)) {
            destinations = destinationRepository.findByParentName("中国");
        } else {

//           获取 国外区域的目的地对象
            Region region = (Region) regionService.get(regionId);
            List<String> ids = region.getRefIds();
            //
            destinations = destinationRepository.findByIdIn(ids);
        }

        //第二层: 查询关联目的地下的子目的地
        //获取数据库广东目的地集合或者区域对象集合的子目的地(广州,深圳)后,封装在目的地对象的children属性集合上
        for (Destination destination : destinations) {
            //设置分页条件对象  截取前5个 默认_id主键排序  然后把对象给findByParentId做为参数,去拼接sql,过滤查询,分页
            // where xx 等于什么 limit xx
            Pageable pageable=PageRequest.of(0,5,Sort.Direction.ASC,"_id");
            //获取所有的目的地对象: 广州目的地对象
            List<Destination> children = destinationRepository.findByParentId(destination.getId(),pageable);
            // 把数据库的子目的地对象集合(比如:城市) 封装在区域对象集合或者中国目的地对象集合的每个元素(比如:广东对象);
            // 赋值给destination对象的属性children
            destination.setChildren(children);
        }
        //返回区域对象集合每个对象对应的所有目的地对象集合
        return destinations;
    }
}
